/*
 * VentanaPrincipal.cpp
 *      Author: sebastian
 */

#include "VentanaPrincipal.h"
#include <vector>

VentanaPrincipal::VentanaPrincipal(const Glib::RefPtr<Gtk::Builder>& builder) {
	pathFondo = "";
	pathAgujero = "";
	this->builder = builder;
	sePulsoNuevo = false;
	dialogo = new DialogoProbabilidades(builder);
	dialogoImagen = new DialogoImagen(builder);
	builder->get_widget("window1",ventana);
	builder->get_widget("dialogCantidad",cantFilasColumnas);
	builder->get_widget("lblNumNivelAdvertencia",numNivelAdvertencia);
	builder->get_widget("btnNuevo",nuevo);
	nuevo->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickNuevo));
	builder->get_widget("btnEditar",editar);
	editar->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickEditar));
	builder->get_widget("btnGuardar",guardar);
	guardar->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickGuardar));
	builder->get_widget("btnSalir",salir);
	salir->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickSalir));
	builder->get_widget("btnSetearTodas",setearATodos);
	setearATodos->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickEstablecerTodas));
	builder->get_widget("textNombre",txtNombreNivel);
	builder->get_widget("boxSetFondo",boxFondo);
	builder->get_widget("boxSetAgujero",boxAgujero);
	builder->get_widget("scrolledwindow1",scroll);
	builder->get_widget("lblColumnas",lblColumnas);
	builder->get_widget("spinMaximoPuntaje",spinMaximoPuntaje);
	builder->get_widget("spinCantFilas",spinFila);
	builder->get_widget("spinCantColumnas",spinColumna);
	builder->get_widget("spinNumeroDeNivel",spinNumeroDeNivel);
	builder->get_widget("spinCantMaxJugadores",spinNroMaxJugadores);
	builder->get_widget("btnSetAgujero",btnSetAgujero);
	btnSetAgujero->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickSetImagenAgujero));
	builder->get_widget("btnSetFondo",btnSetFondo);
	btnSetFondo->signal_clicked().connect(sigc::mem_fun(*this, &VentanaPrincipal::clickSetImagenFondo));
	tabla = 0;
	crearMenu();
}

VentanaPrincipal::~VentanaPrincipal() {
	if (tabla != 0) {
		liberarVectorCeldas();
	}
	if (dialogo != 0){
		delete dialogo;
	}
	if (dialogoImagen != 0) {
		delete dialogoImagen;
	}
}

void VentanaPrincipal::crearTabla(unsigned int filas, unsigned int columnas){
	if( tabla != 0 ) {
		liberarVectorCeldas();
		tabla->hide();
		tabla->resize(filas+1,columnas);
	} else {
		Gtk::Grid* grid3 = 0;
		builder->get_widget("grid3",grid3);
		grid3->show();
		lblColumnas->show();
		setearATodos->show();
		boxFondo->show();
		boxAgujero->show();
		tabla = new Gtk::Table(filas+1,columnas,false);
		tabla->set_row_spacings(0);
		tabla->set_col_spacings(0);
		tabla->set_row_spacing(0,30);
		scroll->add(*tabla);
	}

	int arriba = 0;
	int abajo = 1;
	for(unsigned int i = 0; i < filas+1; i++){
		int izquierda = 0;
		int derecha = 0;
		for(unsigned int j = 0; j< columnas ; j++){
			if (j != 0) izquierda++;
			derecha++;
			CeldaImagen* botonImagen = new CeldaImagen(dialogo);
			celdas.push_back(botonImagen);
			tabla->attach(*botonImagen->getBoton(),izquierda,derecha,arriba,abajo);
		}
		abajo++;
		arriba++;
	}
	tabla->show();
	NoAgujerosGeneradorColumna();
}

void VentanaPrincipal::NoAgujerosGeneradorColumna(){
	unsigned int columnas = spinColumna->get_value_as_int();
	for(unsigned int i = 0; i< columnas ; i++){
		celdas[i]->noPuedeSerAgujero();
	}
}

void VentanaPrincipal::liberarVectorCeldas(){
	if (!celdas.empty()){
		for (unsigned int i = 0 ; i < celdas.size() ; i++){
			tabla->remove(*celdas[i]->getBoton());
			delete celdas[i];
		}
	}
	celdas.clear();
}

void VentanaPrincipal::clickNuevo(){
	bool ejecutar = true;
	if (sePulsoNuevo) {
		ejecutar = pierdeTodo();
	}
	if (ejecutar){
		int resultado = cantFilasColumnas->run();
		cantFilasColumnas->hide();
		if (resultado == Gtk::RESPONSE_ACCEPT){
			sePulsoNuevo = true;
			editando.clear();
			txtNombreNivel->set_text("");
			spinNroMaxJugadores->set_value(2);
			spinMaximoPuntaje->set_value(3000);
			pathFondo.clear();
			pathAgujero.clear();
			Gtk::Image* auxiliar = 0;
			builder->get_widget("imagenAgujero",auxiliar);
			auxiliar->set("estado.gif");
			builder->get_widget("imagenFondo",auxiliar);
			auxiliar->set("estado.gif");
			crearTabla(spinFila->get_value_as_int(),spinColumna->get_value_as_int());
		} else {
			if (!sePulsoNuevo) {
			sePulsoNuevo = false;
			}
		}
	} 	
}

bool VentanaPrincipal::pierdeTodo(){
	bool ejecutar = true;
	Gtk::Dialog* dialogoAdvertencia = 0;
	builder->get_widget("dialog2",dialogoAdvertencia);
	int respuesta = dialogoAdvertencia->run();
	if (respuesta == Gtk::RESPONSE_CANCEL){
		ejecutar = false;
	}
	dialogoAdvertencia->hide();
	return ejecutar;
}

void VentanaPrincipal::clickEditar(){
	bool ejecutar = true;
	if (sePulsoNuevo) {
		ejecutar = pierdeTodo();
	}
	if(ejecutar){
		ElegidorDeArchivos* elegidor = new ElegidorDeArchivos("Abrir");
		int resultado = elegidor->run();
		if (resultado == Gtk::RESPONSE_OK){
			cargarNivelDesdeArchivo(elegidor->get_filename());
			editando += "Se esta editando el archivo = ";
			editando += elegidor->get_filename();
		} else {
			//
		}
		elegidor->hide();
		delete elegidor;
	}
}


void VentanaPrincipal::cargarNivelDesdeArchivo(std::string nombre){
	sePulsoNuevo = true;
	Json::Value root;
	CargaJson levantador;
	int resultado = levantador.getJson(nombre,root);
	if (resultado == 0) {
		pathAgujero = root["imagen de agujero"].asString();
		if (!pathAgujero.empty()){
			if(!archivoExiste(pathAgujero)){
				ImagenJson imagen;
				imagen.setJson(root["Binario Agujero"]);
				imagen.getImagenToPath(pathAgujero);
			}
			Gtk::Image* agujero = 0;
			builder->get_widget("imagenAgujero",agujero);
			agujero->set("estadoOK.gif");
		}
		pathFondo = root["imagen de fondo"].asString();
		if (!pathFondo.empty()){
			if(!archivoExiste(pathFondo)){
				ImagenJson imagen;
				imagen.setJson(root["Binario Fondo"]);
				imagen.getImagenToPath(pathFondo);
			}
			Gtk::Image* fondo = 0;
			builder->get_widget("imagenFondo",fondo);
			fondo->set("estadoOK.gif");
		}
		unsigned int cantFilas = root["cantFilas"].asUInt();
		unsigned int cantColumnas = root["cantColumnas"].asUInt();
		spinFila->set_value(cantFilas);
		spinColumna->set_value(cantColumnas);

		spinMaximoPuntaje->set_value(root["Maximo score"].asUInt());
		spinNumeroDeNivel->set_value(root["numero de nivel"].asUInt());
		txtNombreNivel->set_text(root["nombre de nivel"].asString());
		spinNroMaxJugadores->set_value(root["maxJugadores"].asUInt());

		crearTabla(cantFilas, cantColumnas);

		unsigned int contador = 0;
		for (unsigned int i = 0; i < cantColumnas ; i++){
			std::stringstream aux;
			aux << "Columna " << i;
			celdas[i]->setJson(root["PGeneradores"][aux.str()]);
			contador++;
		}

		for (unsigned int i = 0; i< cantFilas*cantColumnas ; i++){
			std::stringstream s2;
			s2 << "Celda " << i;
			celdas[i+cantColumnas]->setJson(root["PCeldas"][s2.str()]);
			contador++;
		}
	} else {
		//Error
	}

}

void VentanaPrincipal::clickGuardar(){
	if (sePulsoNuevo || !editando.empty()){
		if (!comprobarEstadoCeldas()) {
			Gtk::MessageDialog auxiliar("El estado de las celdas no es apto para guardar");
			auxiliar.run();
		} else {
			Json::Value root;
			std::string nombreArchivo = "nivel_";
			nombreArchivo += spinNumeroDeNivel->get_text().c_str();
			nombreArchivo += ".json";
			bool grabar = true;
			if (archivoExiste(nombreArchivo) && editando.empty()){
				Gtk::Dialog* yaExiste = 0;
				builder->get_widget("dialogYaExiste",yaExiste);
				std::stringstream numeroDeNivel;
				numeroDeNivel << spinNumeroDeNivel->get_value_as_int();
				numNivelAdvertencia->set_text(numeroDeNivel.str());
				int resultado = yaExiste->run();
				if (resultado == Gtk::RESPONSE_CANCEL){
					grabar = false;
				}
				yaExiste->hide();
			}
			if (grabar){
				if(pathAgujero != ""){
					ImagenJson iAgujero;
					iAgujero.armarJson(pathAgujero);
					root["Binario Agujero"] = iAgujero.getJsonImagen();
				} else {
					root["Binario Agujero"] = "";
				}
				if(pathFondo != ""){
					ImagenJson iFondo;
					iFondo.armarJson(pathFondo);
					root["Binario Fondo"] = iFondo.getJsonImagen();
				} else {
					root["Binario Fondo"] = "";
				}
				unsigned int cantFilas = spinFila->get_value_as_int();
				unsigned int cantColumnas =  spinColumna->get_value_as_int();
				root["nombre de nivel"] = txtNombreNivel->get_text().c_str();
				root["cantFilas"] = cantFilas;
				root["cantColumnas"] = cantColumnas;
				root["maxJugadores"] = spinNroMaxJugadores->get_value_as_int();
				root["Maximo score"] = spinMaximoPuntaje->get_value_as_int();
				root["numero de nivel"] = spinNumeroDeNivel->get_value_as_int();

				root["imagen de fondo"] = getNombreFromPath(pathFondo).c_str();
				root["imagen de agujero"] = getNombreFromPath(pathAgujero).c_str();

				unsigned int contador = 0;

				for (unsigned int i = 0; i < cantColumnas ; i++){
					std::stringstream aux;
					aux << "Columna " << i;
					root["PGeneradores"][aux.str()] = celdas[i]->getJson();
					contador++;
				}

				for (unsigned int i = 0; i < cantFilas*cantColumnas ; i++){
					std::stringstream s1;
					s1 << "Celda " << i;
					root["PCeldas"][s1.str()] = celdas[i+cantColumnas]->getJson();
					contador++;
				}

				if (hayAgujeros()){
					root["forma de nivel"] = "Agujeros";
				} else{
					root["forma de nivel"] = "Celdas";
				}
				std::ofstream archivo(nombreArchivo, std::ios_base::out);
				if(archivo.is_open()){
					if(archivo.good()){
						archivo << root;
					}
					archivo.close();
				} else {
					Gtk::MessageDialog auxiliar("Hubo un problema al guardar");
						auxiliar.run();
				}
				Gtk::MessageDialog auxiliar("Guardado");
				auxiliar.run();
			}
		}
	} else {
		Gtk::MessageDialog auxiliar("No hay que guardar");
		auxiliar.run();
	}

}

bool VentanaPrincipal::archivoExiste(std::string& path){
	bool existe = false;
	std::ifstream archivo(path);
	if(archivo.is_open()){
		if (archivo.good()){
			existe = true;
		}
	}
	archivo.close();
	return existe;
}

void VentanaPrincipal::clickSalir(){
	ventana->hide();
}


void VentanaPrincipal::clickEstablecerTodas(){
	dialogo->verCheckAgujero(false);
	bool resultado = dialogo->show();
	if (resultado){
		for (unsigned int i = 0 ; i < celdas.size() ; i++){
			celdas[i]->obtenerDatosDeProbabilidades();
			celdas[i]->cambiarEstado();
		}
	}
}

void VentanaPrincipal::clickSetImagenAgujero(){
	dialogoImagen->setearImagen(pathAgujero);

	pathAgujero = dialogoImagen->show();
	if ( pathAgujero != "") {
		Gtk::Image* agujero = 0;
		builder->get_widget("imagenAgujero",agujero);
		agujero->set("estadoOK.gif");
	}
}

void VentanaPrincipal::clickSetImagenFondo(){
	dialogoImagen->setearImagen(pathFondo);
	pathFondo = dialogoImagen->show();
	if ( pathFondo != "") {
		Gtk::Image* fondo = 0;
		builder->get_widget("imagenFondo",fondo);
		fondo->set("estadoOK.gif");
	}
}


bool VentanaPrincipal::comprobarEstadoCeldas(){
	unsigned int i = 0;
	bool estadoOK = true;
	while (i < celdas.size() && estadoOK){
		estadoOK = celdas[i]->getEstado();
		i++;
	}
	return estadoOK;
}

bool VentanaPrincipal::hayAgujeros(){
	bool hayAgujero = false;
	unsigned int columna = spinColumna->get_value_as_int();
	unsigned int fila = spinFila->get_value_as_int();
	unsigned int i = columna;
	while (i < columna*fila && !hayAgujero){
		hayAgujero = celdas[i]->celdaEsAgujero();
		i++;
	}
	return hayAgujero;
}


std::string VentanaPrincipal::getNombreFromPath(std::string& path){
	std::string resultado = "";
	if (!path.empty()){
		int tamanio = path.size() - 1;
		while (tamanio >=0 && path[tamanio] != '/' ){
			resultado.insert(0,sizeof(path[tamanio]),path[tamanio]);
			tamanio--;
		}
	}
	return resultado;
}


void VentanaPrincipal::crearMenu(){
  m_refActionGroup = Gtk::ActionGroup::create();
  
  m_refActionGroup->add(Gtk::Action::create("FileMenu", "_Archivo"));
  m_refActionGroup->add(Gtk::Action::create("FileNew", Gtk::Stock::NEW),
   sigc::mem_fun(*this, &VentanaPrincipal::clickNuevo));
   
  m_refActionGroup->add(Gtk::Action::create("FileEdit", Gtk::Stock::OPEN),
  sigc::mem_fun(*this, &VentanaPrincipal::clickEditar));
  
  m_refActionGroup->add(Gtk::Action::create("FileSave", Gtk::Stock::SAVE),
   sigc::mem_fun(*this, &VentanaPrincipal::clickGuardar));
  
  m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT),
          sigc::mem_fun(*this, &VentanaPrincipal::clickSalir));

  m_refUIManager = Gtk::UIManager::create();
  m_refUIManager->insert_action_group(m_refActionGroup);

  Gtk::Window* principal = 0;
  builder->get_widget("window1",principal);
  
  principal->add_accel_group(m_refUIManager->get_accel_group());

  Glib::ustring ui_info = 
        "<ui>"
        "  <menubar name='MenuBar'>"
        "    <menu action='FileMenu'>"
        "      <menuitem action='FileNew'/>"
        "      <menuitem action='FileEdit'/>"
        "      <menuitem action='FileSave'/>"
        "      <separator/>"
        "      <menuitem action='FileQuit'/>"
        "    </menu>"
        "  </menubar>"
        "</ui>";
  try
  {
    m_refUIManager->add_ui_from_string(ui_info);
  }
  catch(const Glib::Error& ex)
  {
    std::cerr << "building menus failed: " <<  ex.what();
  }

  Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar");
  if(pMenubar){
	Gtk::Box* cajaMenu = 0;
	builder->get_widget("box7",cajaMenu);
	cajaMenu->pack_start(*pMenubar, Gtk::PACK_SHRINK);
	cajaMenu->show_all_children();
	}
}
